<?php

namespace org\copperforest\oak\authorization;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 * SUPUESTAMENTE AUTHORITY DEVUELVE TEMPLATES
 * 
 */

class Authority
{ //Se encarga de una politica de seguridad

    private static $_NAMES = array( );
    private static $_IDS = array( );
    static $_authorities = array( );
    static $_old_authorities;
    static $_min_id;
    protected $id;
    protected $name;

    //Arora, tengo que encontrar un sistema para asociar a cada array de roles un id, el contexto de seguridad
    //para ello tengo que serializar el array de roles

    private function __construct( $name, $id )
    {

        $this->id = $id;
        $this->name = $name;

        self::$_authorities[ $name ] = $this;
    }

    function getInstance( $name )
    {
        if ( !isset( self::$_authorities[ $name ] ) )
                self::$_authorities[ $name ] = new self::$_CLASSES[ $name ]( $name,
                    $id );

        return self::$_authorities[ $name ];
    }

    function _getInstance( $id )
    {
        $name = self::$_NAMES[ $id ];

        if ( !isset( self::$_authorities[ $name ] ) )
                self::$_authorities[ $name ] = new self::$_CLASSES[ $name ]( $name,
                    $id );

        return self::$_authorities[ $name ];
    }

    function getId()
    {
        return $this->id;
    }

    function getName()
    {
        return $this->name;
    }

    function query( $rol, &$result, $params = null )
    {
        
    }

    /* function queryById( $rol, $id ){

      } */

    function _cf_search_authorities( $path, &$authorities )
    {


        $files = array_diff( scandir( $path ), array( '.', '..' ) );

        $domXPath = null;
        $xml = null;

        foreach ( $files as $f ) {

            if ( is_dir( $path . $f ) )
                    self::_cf_search_policies( $path . $f . DIRECTORY_SEPARATOR,
                        $authorities );

            else {

                $dotpos = strrpos( $f, '.' );
                $ext = substr( $f, $dotpos + 1 );

                if ( $ext == 'xml' ) {

                    $name = substr( $f, 0, $dotpos );

                    $xml = new DOMDocument();
                    $id = null;

                    if ( isset( $policies[ $name ] ) )
                            throw new Exception( 'There is another xml files with the authority\'s name \'' . $name . '\': ' . $path . $f );

                    if ( $xml->load( $path . $f ) && $xml->schemaValidate( CLASS_PATH . 'authority.xsd' ) ) {

                        $domXPath = new DOMXPath( $xml );

                        $authorities[ $name ] = array(
                            'file' => $path . $f,
                            'class' => trim( $domXPath->query( '/authority/class' )->item( 0 )->nodeValue )
                        );
                    } else if ( isset( self::$_old_authorities[ $name ] ) )
                            throw new Exception( 'Can\'t validate "' . $path . $f . '" for "' . $name . '"(' . $id . ') authority' );

                    unset( $xml, $domXPath );
                }
            }
        }
    }

    static function _deploy( $link )
    {




        /*
          function libxml_display_errors() {
          $errors = libxml_get_errors();

          foreach ($errors as $error) {
          $return = "<br/>\n";
          switch ($error->level) {
          case LIBXML_ERR_WARNING:
          $return .= "<b>Warning $error->code</b>: ";
          break;
          case LIBXML_ERR_ERROR:
          $return .= "<b>Error $error->code</b>: ";
          break;
          case LIBXML_ERR_FATAL:
          $return .= "<b>Fatal Error $error->code</b>: ";
          break;
          }
          $return .= trim($error->message);
          if ($error->file) {
          $return .=    " in <b>$error->file</b>";
          }
          $return .= " on line <b>$error->line</b>\n";

          echo $return;
          }
          libxml_clear_errors();
          }

          // Enable user error handling
          libxml_use_internal_errors(true);
         */


        $authorities = array( );
        self::_cf_search_authorities( CF_CLASS_PATH, $authorities );

        self::$_IDS = array( );
        self::$_NAMES = array( );


        //_old_authorities is a authorities name indexed array (as demostrated in prueba0 is the fast way)
        if ( file_exists( CF_OLD_CONFIG_PATH . 'authority.config' ) )
                $old_authorities = unserialize( file_get_contents( CF_OLD_CONFIG_PATH . 'authority.config' ) );
        else $old_authorities = array( );

        $min_id = 0;
        foreach ( $authorities as $name => $a ) {

            //we keep the old policies id's and reasign the empty indexes
            if ( isset( $old_authorities[ $name ] ) )
                    $id = $old_authorities[ $name ];

            else {

                while ( in_array( $min, $old_authorities ) )
                    $min_id++;
                $id = $min_id;
                $min_id++;
            }

            self::$_IDS[ $name ] = $id;
            self::$_NAMES[ $id ] = $name;
            self::$_CLASSES[ $name ] = $a[ 'class' ];
        }

        unset( $old_authorities, $min_id );

        file_put_contents( CF_CONFIG_PATH . 'authority.config', self::$_IDS );


        //Por cada clase tiene que haber un deploy pero por cada instancia tengo que ahcer un configure
        $classes_stock = array( );
        foreach ( $authorities as $name => $a ) {

            if ( !in_array( $a[ 'class' ], $classes_stock ) ) {

                $a[ 'class' ]::_deploy( $link );
                $classes_stock[ ] = $a[ 'class' ];
            }

            $a[ 'class' ]::_configure( $a[ 'file' ] );
        }
    }

    static function _init()
    {

        if ( file_exists( CF_CONFIG_PATH . 'authority.config' ) ) {

            self::$_IDS = file_get_contents( CF_CONFIG_PATH . 'authority.config' );
            self::$_NAMES = array_flip( self::$_IDS );
        }
    }

}

Authority::_init();
?>
